#pragma once

/**
 * @file tcp_socket.h
 * @brief TCP套接字实现
 * @details 提供TCP套接字的创建、连接、数据发送和接收功能
 */

#include <functional>

#include "socket_utils.h"
#include "logging.h"

namespace Common {
  /**
   * @namespace Common
   * @brief 包含常用工具类和函数的命名空间
   */
  /**
   * @brief TCP缓冲区大小（字节）
   * @details 用于发送和接收数据的缓冲区大小，设置为64MB
   */
  constexpr size_t TCPBufferSize = 64 * 1024 * 1024;

  /**
   * @struct TCPSocket
   * @brief TCP套接字类
   * @details 提供TCP网络通信的基本功能，包括连接、发送和接收数据
   */
  struct TCPSocket {
    /**
     * @brief 构造函数
     * @param logger 日志对象引用，用于记录套接字操作
     */
    explicit TCPSocket(Logger &logger)
        : logger_(logger) {
      outbound_data_.resize(TCPBufferSize);
      inbound_data_.resize(TCPBufferSize);
    }

    /**
     * @brief 创建并连接TCP套接字
     * @param ip IP地址
     * @param iface 网络接口
     * @param port 端口号
     * @param is_listening 是否为监听模式
     * @return 套接字文件描述符，失败时返回负值
     */
    auto connect(const std::string &ip, const std::string &iface, int port, bool is_listening) -> int;

    /**
     * @brief 发送和接收数据
     * @details 发送缓冲区中的数据，并检查是否有新数据可读。如果有新数据，则调用回调函数处理
     * @return 如果接收到数据返回true，否则返回false
     */
    auto sendAndRecv() noexcept -> bool;

    /**
     * @brief 将数据写入发送缓冲区
     * @param data 要发送的数据指针
     * @param len 数据长度（字节）
     */
    auto send(const void *data, size_t len) noexcept -> void;

    /**
     * @brief 删除的默认、拷贝和移动构造函数及赋值运算符
     * @details 禁止默认构造、拷贝和移动语义，确保套接字资源的正确管理
     */
    TCPSocket() = delete;

    TCPSocket(const TCPSocket &) = delete;

    TCPSocket(const TCPSocket &&) = delete;

    TCPSocket &operator=(const TCPSocket &) = delete;

    TCPSocket &operator=(const TCPSocket &&) = delete;

    /**
     * @brief 套接字文件描述符
     * @details 系统分配的套接字文件描述符，初始值为-1表示未初始化
     */
    int socket_fd_ = -1;

    /**
     * @brief 发送和接收缓冲区及其读写索引
     * @details 用于存储待发送和已接收的数据，以及跟踪当前的读写位置
     */
    std::vector<char> outbound_data_;
    size_t next_send_valid_index_ = 0;
    std::vector<char> inbound_data_;
    size_t next_rcv_valid_index_ = 0;

    /**
     * @brief 套接字属性
     * @details 存储套接字的地址、端口等属性信息
     */
    struct sockaddr_in socket_attrib_{};

    /**
     * @brief 数据接收回调函数
     * @details 当有新数据可用时调用的函数，用于处理接收到的数据
     */
    std::function<void(TCPSocket *s, Nanos rx_time)> recv_callback_ = nullptr;

    /**
     * @brief 时间字符串缓存
     * @details 用于日志记录的时间字符串缓存
     */
    std::string time_str_;
    
    /**
     * @brief 日志对象引用
     * @details 用于记录套接字操作的日志信息
     */
    Logger &logger_;
  };
}
